package dev2dev.textclient.conv;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author jinbing.yao
 * @createTime 2023-11-23 09:13
 **/
public class G711AUtil {
    private static byte encode(int pcm) {
        //Get the sign bit. Shift it for later use
        //without further modification
        int sign = (pcm & 0x8000) >> 8;
        //If the number is negative,
        //make it positive (now it's a magnitude)
        if (sign != 0)
            pcm = -pcm;
        //The magnitude must fit in 15 bits to avoid overflow
        if (pcm > 0x7fff) pcm = 0x7fff;


        int exponent = 7;
        //Move to the right and decrement exponent
        //until we hit the 1 or the exponent hits 0
        for (int expMask = 0x4000; (pcm & expMask) == 0
                && exponent > 0; exponent--, expMask >>= 1) {
        }
        int mantissa = (pcm >> ((exponent == 0) ? 4 : (exponent + 3))) & 0x0f;

        //The a-law byte bit arrangement is SEEEMMMM
        //(Sign, Exponent, and Mantissa.)
        byte alaw = (byte) (sign | exponent << 4 | mantissa);

        //Last is to flip every other bit, and the sign bit (0xD5 = 1101 0101)
        return (byte) (alaw ^ 0xD5);
    }
//
    public static int bytesToInt(byte[] a){
        int ans=0;
//        for(int i=0;i<2;i++){
//            ans<<=8;//左移 8 位
//            ans|=a[1-i];//保存 byte 值到 ans 的最低 8 位上
//        }
        for(int i=0;i<4;i++){
            ans<<=8;//左移 8 位
            ans|=a[3-i];//保存 byte 值到 ans 的最低 8 位上
        }
        return ans;
    }


    /**
     * byte数组中取int数值，本方法适用于(低位在前，高位在后)的顺序。
     *
     * @param ary    byte数组
     * @param offset 从数组的第offset位开始
     * @return int数值
     */
    public static int bytesToInt(byte[] ary, int offset) {
        int value;
        value = (int) ((ary[offset] & 0xFF)
                | ((ary[offset + 1] << 8) & 0xFF00));
//                | ((ary[offset + 2] << 16) & 0xFF0000)
//                | ((ary[offset + 3] << 24) & 0xFF000000));
        return value;
    }

    /**
     * 把 byte[] 均拆成 list
     *
     * @param array size 倍长度的byte
     * @param size  每组 size 个byte[]
     * @return
     */
    public static List<byte[]> splitArray(byte[] array, int size) {
        List<byte[]> result = new ArrayList<>();
        for (int i = 0; i < array.length; i += size) {
            byte[] subArray = Arrays.copyOfRange(array, i, Math.min(i + size, array.length));
            result.add(subArray);
        }
        return result;
    }

    /**
     * @param bytes 4 长度是4的倍数
     * @return PCM转G711
     */
    public static byte[] pcmToG711A(byte[] bytes) {
        List<byte[]> list = splitArray(bytes, 4);
        byte[] resBytes = new byte[bytes.length / 4];
        for (int i = 0; i < list.size(); i++) {
            resBytes[i] = encode(bytesToInt(list.get(i),2));
        }
        return resBytes;
    }


    public static void main(String[] args) {
        byte[] bytes = new byte[]{0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03};


        byte[] resBytes =    pcmToG711A(bytes);
        pcmToG711A(bytes);
    }

}
